<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Simple HTTP PING</title>
    <style>
        body {
            font-family: Arial, serif;
        }
    </style>
</head>
<body>
<div>©Copyright 2024 WeiYuanStudio</div>
<h1>Simple HTTP PING</h1>
<div style="display: flex; flex-direction: column">
    <label>
        Random ECHO Length:
        <input id="echo-context-length" type="number" value="10240"/>
    </label>
    <label>
        <textarea id="message-textarea" style="width: 400px; height: 240px"
                  placeholder="payload">== TECH OTAKUS SAVE THE WORLD ==</textarea>
    </label>
    <div>Status: <span id="display-status" style="font-weight: bold">N/A</span></div>
    <div>Latency: <span id="display-latency" style="font-weight: bold">N/A</span></div>
    <div>Response: <span id="display-echo" style="font-weight: bold; color: darkgreen">N/A</span></div>
    <div>
        <button id="single-echo">ECHO</button>
        <button id="single-ping">PING</button>
        <button id="loop-echo">LOOP ECHO</button>
        <button id="loop-ping">LOOP PING</button>
        <button id="loop-echo-random">LOOP ECHO RANDOM</button>
        <button id="stop">STOP</button>
    </div>
</div>

<br/>
<table border="1">
    <thead>
    <tr>
        <th>SEQ</th>
        <th>SEND_TIME</th>
        <th>TYPE</th>
        <th>CONTENT</th>
        <th>RESPONSE</th>
        <th>LATENCY</th>
    </tr>
    </thead>
    <tbody id="tbody">
    <tr>
        <td>1</td>
        <td>2024-04-01 12:00:00</td>
        <td>PING</td>
        <td>-DEMO-</td>
        <td>-DEMO-</td>
        <td>100ms</td>
    </tr>
    </tbody>
</table>
<script>
    var sequence = 1; //请求序列
    var testLog = []; //测试日志
    var intervalHolder = null;

    function shorter(text) {
        if (text.length > 40) {
            return text.substring(0, 10) + "......" + text.substring(text.length - 10, text.length - 1) + " 【LENGTH: " + text.length + "】";
        }
        return text;
    }

    function displayInfo(latency, response) {
        response = shorter(response);
        document.getElementById('display-latency').innerText = latency + "ms";
        document.getElementById('display-echo').innerText = response;
    }

    function creatTd(text) {
        var td = document.createElement('td');
        td.innerText = text;
        return td;
    }

    function dateFormat(date) {
        var d = date.getDate();
        var m = date.getMonth() + 1;
        var y = date.getFullYear();
        var h = date.getHours();
        var min = date.getMinutes();
        var s = date.getSeconds();
        return '' + y + '/' + (m <= 9 ? '0' + m : m) + '/' + (d <= 9 ? '0' + d : d)
            + " " + (h <= 9 ? '0' + h : h)
            + ":" + (min <= 9 ? '0' + min : min)
            + ":" + (s <= 9 ? '0' + s : s);
    }

    function renderTable(testLog) {
        var tBody = document.getElementById('tbody');
        tBody.innerHTML = "";
        for (var i = 0; i < testLog.length; ++i) {
            var row = testLog[i];
            var tr = document.createElement('tr')

            var d = new Date(row.sendTime);
            var dateTime = dateFormat(d);
            tr.appendChild(creatTd(row.seq));
            tr.appendChild(creatTd(dateTime));
            tr.appendChild(creatTd(row.type));
            tr.appendChild(creatTd(shorter(row.content)));
            tr.appendChild(creatTd(shorter(row.response)));
            tr.appendChild(creatTd(row.latency === "TIMEOUT" ? "TIMEOUT" : row.latency + "ms"));

            tBody.appendChild(tr);
        }
    }

    function displayTable(sendTime, type, content, response, latency) {
        testLog.push({
            seq: ++sequence,
            sendTime: sendTime,
            type: type,
            content: content,
            response: response,
            latency: latency
        });

        if (testLog.length > 10) {
            testLog.shift();
        }

        renderTable(testLog);
        console.log(testLog);
    }

    function generateRandomStringByLength(length) {
        var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        var result = '';
        var charactersLength = characters.length;

        for (let i = 0; i < length; i++) {
            var randomIndex = Math.floor(Math.random() * charactersLength);
            result += characters[randomIndex];
        }

        return result;
    }

    function generateRandomString() {
        try {
            var contextLength = document.getElementById('echo-context-length').value;
            var number = parseInt(contextLength);
            if (number > 0) {
                return generateRandomStringByLength(number);
            } else {
                return generateRandomStringByLength(1024);
            }
        } catch (e) {
            return generateRandomStringByLength(1024);
        }
    }

    function displayTableTimeOut(tsStart, type) {
        displayTable(tsStart, type, 'NULL', 'NULL', 'TIMEOUT');
    }

    function singlePing() {
        // 构造完整的URL，包括查询参数
        var url = '/ping';
        // 创建一个新的XMLHttpRequest对象
        var xhr = new XMLHttpRequest();
        var tsStart = new Date().getTime();
        var timeout = setTimeout(displayTableTimeOut, 10 * 1000, tsStart, 'PING');
        // 初始化请求
        xhr.open('GET', url, true);
        // 设置响应处理函数
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                var tsEnd = new Date().getTime();
                var latency = tsEnd - tsStart;
                // 请求成功完成，处理响应
                var responseText = xhr.responseText;
                displayInfo(latency, responseText);
                displayTable(tsStart, 'PING', 'NULL', responseText, latency);
                clearTimeout(timeout);
            }
        };
        // 发送请求
        xhr.send();
    }

    function singleEcho(messageContent) {
        // 构造完整的URL，包括查询参数
        var url = '/echo?message=' + encodeURIComponent(messageContent);
        // 创建一个新的XMLHttpRequest对象
        var xhr = new XMLHttpRequest();
        var tsStart = new Date().getTime();
        var latency = -1; // 延迟
        var timeout = setTimeout(displayTableTimeOut, 10 * 1000, tsStart, 'ECHO');
        // 初始化请求
        xhr.open('GET', url, true);
        // 设置响应处理函数
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                var tsEnd = new Date().getTime();
                latency = tsEnd - tsStart;
                // 请求成功完成，处理响应
                var responseText = xhr.responseText;
                displayInfo(latency, responseText);
                displayTable(tsStart, 'ECHO', messageContent, responseText, latency);
                clearTimeout(timeout);
            }
        };
        // 发送请求
        xhr.send();
    }

    function randomEcho() {
        // 获取textarea中的文本
        var messageContent = generateRandomString();
        singleEcho(messageContent);
    }

    function tryClearInterval(intervalHolder) {
        if (intervalHolder != null) {
            try {
                clearInterval(intervalHolder);
                document.getElementById("display-status").innerText = "N/A";
            } catch (e) {
                console.log(e)
            }
        }
    }

    function init() {
        document.getElementById('single-echo').addEventListener('click', function () {
            // 获取textarea中的文本
            var messageContent = document.getElementById('message-textarea').value;
            singleEcho(messageContent);
        });

        document.getElementById('single-ping').addEventListener('click', function () {
            singlePing();
        });

        document.getElementById('loop-echo').addEventListener('click', function () {
            tryClearInterval(intervalHolder);
            intervalHolder = setInterval(function () {
                document.getElementById("display-status").innerText = "LOOP ECHO";
                var messageContent = document.getElementById('message-textarea').value;
                singleEcho(messageContent);
            }, 1000);
        });

        document.getElementById('loop-ping').addEventListener('click', function () {
            tryClearInterval(intervalHolder);
            intervalHolder = setInterval(function () {
                document.getElementById("display-status").innerText = "LOOP PING";
                singlePing();
            }, 1000);
        });

        document.getElementById('loop-echo-random').addEventListener('click', function () {
            tryClearInterval(intervalHolder);
            intervalHolder = setInterval(function () {
                document.getElementById("display-status").innerText = "LOOP ECHO RANDOM";
                randomEcho();
            }, 1000);
        });

        document.getElementById('stop').addEventListener('click', function () {
            tryClearInterval(intervalHolder);
        });
    }

    init();
</script>
</body>
</html>
